#pragma once
#include <string>
#include <cstring>
#include <fstream>
#include <unordered_map>
#include <sys/types.h>  
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <pthread.h>
#include <signal.h>
#include "ThreadPool.hpp"
#include "Task.hpp"
#include "Daemon.hpp"

//云服务器无法绑定公网ip
//#define defaultip "119.29.155.99"
#define defaultip "0.0.0.0"
#define defaultport 12312
#define backlog 5

std::unordered_map<std::string,std::string> dict;

enum{
    SocketError = 2,
    BindError,
    ListenError
};

class TcpServer
{
public:
    TcpServer(const uint16_t& port = defaultport, const std::string& ip = defaultip) : port_(port),ip_(ip)
    {
        //std::cout<<port_<<" "<<ip_<<std::endl;
    }

    //服务器初始化, socket, bind, listen
    void InitServer()
    {
        //1.创建socket
        listensock_ = socket(AF_INET,SOCK_STREAM,0);
        if(listensock_ < 0){
            Log("ERROR","create socket error, erron: %d, errstring: %s", errno, strerror(errno));
            exit(SocketError);
        }
        Log("info","create socket success, listensock_: %d", listensock_);

        //
        int optval = 1;
        setsockopt(listensock_, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));

        //2. bind
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(port_);
        local.sin_addr.s_addr = inet_addr(ip_.c_str());

        if( bind(listensock_,(struct sockaddr*)&local,sizeof(local)) < 0){
            Log("ERROR","bind error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(BindError);
        }
        Log("info","bind socket success, listensock_: %d",listensock_);

        //3. listen启动监听
        if( listen(listensock_,backlog) < 0){
            Log("ERROR","listen error, errno: %d, errstring: %s", errno, strerror(errno));
            exit(ListenError);
        }
        Log("info","listen socket success, listensock_: %d",listensock_);
    }

    //服务器启动, accept接受连接, pthread_create处理
    void Start()
    {
        //守护进程化
        Daemon();

        //初始化dict
        // 打开文件
        std::ifstream inFile("./word.txt");
        if (!inFile) {
            Log("Error","无法打开 word.txt 文件");
        }
        
        std::string line;
        while (std::getline(inFile, line)) {
            // 查找分隔符 ':'
            size_t pos = line.find(':');
            if (pos != std::string::npos) {
                // 提取英文单词和翻译
                std::string word = line.substr(0, pos);
                std::string translation = line.substr(pos + 1);
                
                // 去除可能的空白字符
                word.erase(word.find_last_not_of(" \t") + 1);
                translation.erase(0, translation.find_first_not_of(" \t"));
                
                // 添加到字典
                dict[word] = translation;
            }
        }
        // 关闭文件
        inFile.close();


        //忽略 SIGPIPE 信号
        signal(SIGPIPE,SIG_IGN);
        //线程池单例初始化, 和启动
        auto threadpool = ThreadPool<Task*>::GetInstance(5,30);
        threadpool.Start();

        Log("info","tcpserver is runnig....");
        for(;;){
            //1.获取新连接
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(listensock_,(struct sockaddr*)&client,&len);//阻塞等待
            if(sockfd < 0){
                Log("waring","accept waring, listensock_: %d", listensock_);
                continue;
            }
            //根据新连接进行通信

            uint16_t clientport = ntohs(client.sin_port);
            char ipstr[32];
            inet_ntop(AF_INET,&(client.sin_addr),ipstr,sizeof(ipstr));
            Log("info","get a new link, sockfd: %d, client ip: %s, client port: %d", sockfd, ipstr, clientport);

            //线程池版本
            Task *td = new Task(sockfd,ipstr,clientport,dict);
            threadpool.push(td);
        }
    }  

    ~TcpServer() 
    {
        if(listensock_ > 0){
            close(listensock_);
        }
    }
private:
    int listensock_;
    uint16_t port_;
    std::string ip_;
};